/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.utils;

public class NetworkDialer implements ThreadScheduable {
    
    
    // CONNECT TO INTERNET VIA DIALUP BEFORE TRYING TO EXECUTE ANY NETWORK COMMANDS
    public static final String NETWORK_VIA_DIALUP_STR = "network.connect.dialup";
    public static final String NETWORK_NAME_STR = "network.connect.name";
    public static final String NETWORK_USERNAME_STR = "network.connect.username";
    public static final String NETWORK_PASSWORD_STR = "network.connect.password";
    
    public static boolean NETWORK_VIA_DIALUP= Settings.getBoolean(NETWORK_VIA_DIALUP_STR,false);
    public String NETWORK_NAME= Settings.getString(NETWORK_NAME_STR,"NOTSET");
    public String NETWORK_USERNAME= Settings.getString(NETWORK_USERNAME_STR,"NOTSET");
    public String NETWORK_PASSWORD= Settings.getString(NETWORK_PASSWORD_STR,"NOTSET");
    
    private boolean CONNECTED = false;
    private Integer disconnect_time = null;
    
    private static NetworkDialer networkDialer = null;
    
    private NetworkDialer(Integer disconnect_time) {
        this.disconnect_time = disconnect_time;
    }
    
    public NetworkDialer(String NETWORK_NAME){
        this.NETWORK_NAME = NETWORK_NAME;
    }
    
    public NetworkDialer() {}
    
    public static NetworkDialer getNetworkDialer() {
        if (networkDialer == null) {
            networkDialer = new NetworkDialer();
        }
        return networkDialer;
    }
    
    public void connect(Integer disconnect_time)
    throws Throwable {
        if (CONNECTED) {return;}
        if (Utils.OS_WINDOWS) {
            connectNT(NETWORK_NAME,NETWORK_USERNAME,NETWORK_PASSWORD);
            CONNECTED = true;
            if (disconnect_time != null) {
                ThreadSchedule.add(new NetworkDialer(disconnect_time));
            }
        } else {
            throw new BindException("Current OS not supported for Network Dailer");
        }
    }
    
    public boolean connected() {
        return (CONNECTED);
    }
    
    public void disconnect()
    throws Throwable {
        if (!CONNECTED) {
            return;
        }
        if (Utils.OS_WINDOWS) {
            disconnectNT(NETWORK_NAME,NETWORK_USERNAME,NETWORK_PASSWORD);
            CONNECTED = false;
        } else {
            throw new BindException("Current OS not supported for Network Dailer");
        }
    }
    
    private void connectNT(String network_name,String username,String password) throws Throwable {
        Log.trace.out("Network Dialer","rasdial "+network_name+" "+username+" "+password);
        Process p = Runtime.getRuntime().exec("rasdial "+network_name+" "+username+" "+password);
        p.waitFor();
        byte buffer[] = new byte[1024];
        int r = p.getInputStream().read(buffer);
        if (new String(buffer,0,r).indexOf("Successfully connected to "+ network_name) == -1) {
            throw new BindException("Network Dialer: Connection failed ["+new String(buffer,0,r)+"]");
        }
    }
    
    private void disconnectNT(String network_name,String username,String password) throws Throwable {
        Log.trace.out("Network Dialer","rasdial "+network_name+" /DISCONNECT");
        Process p = Runtime.getRuntime().exec("rasdial "+network_name+" /DISCONNECT");
        p.waitFor();
        byte buffer[] = new byte[1024];
        int r = p.getInputStream().read(buffer);
        if (new String(buffer,0,r).indexOf("Command completed successfully") == -1) {
            throw new BindException("Network Dialer: Disconnection failed ["+new String(buffer,0,r)+"]");
        }
    }
    
    public boolean keepAlive() {return false;}
    public int sleepTime() {return 0;}
    
    public void process()
    throws Throwable {
        Thread.sleep(disconnect_time.intValue());
        disconnect();
    }
    
    public void close() throws Throwable {}
}
